package com.example.emailcraft.utils;

import com.example.emailcraft.entity.Users;
import com.example.emailcraft.handler.GlobalExceptionHandler;
import com.example.emailcraft.mapper.UsersMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Component;

@Component
@Slf4j
public class UserUtils {

    @Autowired
    private UsersMapper usersMapper;

    @Autowired
    private PasswordEncoder passwordEncoder;

    private static final int MAX_ATTEMPTS = 5;

    /**
     * 用户认证
     * @param username 用户名
     * @param password 密码
     * @return 认证成功的用户实体
     * @throws GlobalExceptionHandler.AccountLockedException 账户锁定
     * @throws GlobalExceptionHandler.InvalidCredentialsException 密码错误
     * @throws GlobalExceptionHandler.UserNotFoundException 用户不存在
     */
    public Users authenticate(String username, String password) {
        // 查询用户
        Users user = usersMapper.findByUsername(username);
        if (user == null) {
            throw new GlobalExceptionHandler.UserNotFoundException();
        }
        log.info("用户认证: {}", user);

        // 验证密码（恒定时间比较）
        if (!passwordEncoder.matches(password, user.getPasswordHash())) {
            // 记录失败尝试
            user.setFailedAttempts(user.getFailedAttempts() + 1);
            usersMapper.updateById(user);

            if (user.getFailedAttempts() >= MAX_ATTEMPTS) {
                user.setIsLocked(1);
                usersMapper.updateById(user);
                throw new GlobalExceptionHandler.AccountLockedException();
            }

            throw new GlobalExceptionHandler.InvalidCredentialsException();
        }

        // 检查账户状态
        if (user.getIsLocked() == 1) {
            throw new GlobalExceptionHandler.AccountLockedException();
        }

        // 重置失败次数
        if (user.getFailedAttempts() > 0) {
            user.setFailedAttempts(0);
            usersMapper.updateById(user);
        }

        return user;
    }
}